﻿#if false
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;

namespace Util.IO
{
    // This has less overhead and better performance than IEnumerable if array
    // is accessed in large size.
    public abstract class InputStream<T>
    {
        public abstract int ReadSome(T[] array, int index, int count);
    }

    // This has less overhead and better performance than ICollection if array
    // is accessed in large size.
    public abstract class OutputStream<T> : IDisposable
    {
        protected virtual void Dispose(bool disposing) { }

        public abstract int WriteSome(T[] array, int index, int count);

        public void Dispose()
        {
            Dispose(true);
        }

        public virtual void Write(T[] array, int index, int count)
        {
            if (array == null)
                throw new ArgumentNullException("array");
            if (index < 0)
                throw new ArgumentOutOfRangeException("index");
            if (count < 0 || index + count > array.Length)
                throw new ArgumentOutOfRangeException("count");

            while (count > 0)
            {
                int actual = WriteSome(array, index, count);
                if (actual < 0)
                    throw new ArgumentException("WriteSome() must return a non-negative value.");
                if (actual == 0)
                    throw new EndOfStreamException("Cannot write enough bytes.");
                index += actual;
                count -= actual;
            }
        }

        public virtual void Write(T elem)
        {
            Write(new T[] { elem }, 0, 1);
        }
    }

    public class ValueTypeOutputStream<T> : OutputStream<T>
        where T : struct
    {
        private static int elemSize = Marshal.SizeOf(typeof(T));

        private Stream baseStream;
        private bool leaveOpen;

        public ValueTypeOutputStream(Stream baseStream, bool leaveOpen)
        {
            this.baseStream = baseStream;
            this.leaveOpen = leaveOpen;
        }

        protected override void Dispose(bool disposing)
        {
            if (baseStream != null)
            {
                if (!leaveOpen)
                    baseStream.Dispose();
                baseStream = null;
            }
        }

        public override int WriteSome(T[] array, int index, int count)
        {
            byte[] buffer = new byte[count * elemSize];
            Buffer.BlockCopy(array, index * elemSize, buffer, 0, buffer.Length);
            baseStream.Write(buffer, 0, buffer.Length);
            return count;
        }

        public Stream BaseStream { get { return baseStream; } }
    }

    public class ByteOutputStream : ValueTypeOutputStream<byte>
    {
        public ByteOutputStream(Stream baseStream, bool leaveOpen)
            : base(baseStream, leaveOpen) { }

        public override int WriteSome(byte[] array, int index, int count)
        {
            BaseStream.Write(array, index, count);
            return count;
        }
    }

    public class EncodedIntegerOutputStream : ValueTypeOutputStream<int>
    {
        public EncodedIntegerOutputStream(Stream baseStream, bool leaveOpen)
             : base(baseStream, leaveOpen) { }

        public override int WriteSome(int[] array, int index, int count)
        {
            byte[] buffer = new byte[5];
            for (int i = 0; i < count; i++)
            {
                int n = Encode7BitInteger(array[index + i], buffer);
                BaseStream.Write(buffer, 0, n);
            }
            return count;
        }

        public static int Encode7BitInteger(int value, byte[] buffer)
        {
            int i = 0;
            uint x = (uint)value;
            do
            {
                buffer[i++] = (byte)(x & 0x7F);
                x >>= 7;
            }
            while (x != 0);
            return i;
        }
    }
}
#endif
